home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_300
/
355_02
/
slk2.exe
/
SPP
/
DCL.C
next >
Wrap
C/C++ Source or Header
|
1991-06-09
|
16KB
|
795 lines
/*
Shelock Preprocessor -- Part II -- Declaration parsing routines.
Source: dcl.c
Started: September 26, 1987
Version:
May 24, 1988
February 16, 1989
periods removed from error messages.
Spurious warning removed from type_ntail().
Set prev_dcl = 0 to get rid of error message.
June 22, 1989
Bug fix in type_tail().
curly_ok_flag kludge in i_list().
PUBLIC DOMAIN SOFTWARE
Sherlock, including the SPP, SDEL and SDIF programs, was placed in
the public domain on June 15, 1991, by its author,
Edward K. Ream
166 North Prospect Ave.
Madison, WI 53705.
(608) 257-0802
Sherlock may be used for any commercial or non-commercial purpose.
DISCLAIMER OF WARRANTIES
Edward K. Ream (Ream) specifically disclaims all warranties,
expressed or implied, with respect to this computer software,
including but not limited to implied warranties of merchantability
and fitness for a particular purpose. In no event shall Ream be
liable for any loss of profit or any commercial damage, including
but not limited to special, incidental consequential or other damages.
*/
#include "spp.h"
/* Declare local routines of this file. */
static void array (void);
static void dcl_enum (void);
static void dcl_struct (void);
static void fp_list (en_scope);
static void function (en_scope);
static void initializer (void);
static void i_list (void);
static void t_list (void);
static bool type_head (en_scope scope);
static en_tokens type_tail (en_scope scope);
static void type_ntail (void);
/* =============== Global variables =============== */
/* Indicates inside function definition. Used by function() and dcl(). */
/* Set to FALSE by program. Set to true by function(). */
static bool func_def; /* TRUE if a function DEFINTION was seen. */
/* Used by function() to see whether function def should give a warning. */
static int prev_dcl; /* Number of previous sub-declarations. */
/* =============== Global routines =============== */
/*
Parse the local variables of a block.
*/
void
block_dcls(void)
{
SL_NAME(fn_name, "block_dcls");
TRACETOK(fn_name);
while (is_type()) {
dcl(BLOCK_SCOPE);
}
RETURN_VOID(fn_name);
}
/*
Parse a single declaration or function definition.
Semicolon ends a declaration but not a function definition.
*/
void
dcl(en_scope scope)
{
SL_NAME(fn_name, "dcl");
TRACETOK(fn_name);
TRACEPN(fn_name, printf("(%s)\n", pr_scope(scope)));
/* Reset semantics for a new declaration. */
sd_dcl(scope);
allow_mkeys();
if (type_head(scope) == TRUE) {
if (func_def && scope == OUTER_SCOPE) {
/* We saw a bare function definition. */
TRACEP(fn_name, printf("bare function complete\n"));
prev_dcl = 0;
RETURN_VOID(fn_name);
}
else {
/* We saw a stand-alone struct\union or enum. */
must(SEMICOLON_TOK);
RETURN_VOID(fn_name);
}
}
/* 2/16/89 */
for (prev_dcl = 0; ;) {
type_tail(scope);
if (scope == OUTER_SCOPE && func_def) {
/* We ARE at the end of the dcl. */
if (is(COMMA_TOK)) {
error("Comma following function body ignored");
get_token();
}
/* 2/16/89 */
prev_dcl = 0;
break;
}
else if (is(COMMA_TOK)) {
sd_end(scope, COMMA_TOK);
get_token();
/* 2/16/89 */
prev_dcl++;
}
else if (is(SEMICOLON_TOK)) {
sd_end(scope, SEMICOLON_TOK);
get_token();
/* 2/16/89 */
prev_dcl = 0;
break;
}
else {
err3( "Unexpected end of declaration at '",
pr_tok(),
"', comma or semicolon expected");
needend(SEMICOLON_TOK);
/* 2/16/89 */
prev_dcl = 0;
break;
}
}
RETURN_VOID(fn_name);
}
/*
A program is nothing but a list of declarations and definitions.
*/
void
program(void)
{
SL_NAME(fn_name, "program");
TRACETOK(fn_name);
/* Get the first token of the program. */
get_token();
for (;;) {
/* Not in function definition yet. */
func_def = FALSE;
allow_mkeys();
if (is_type() || is(ID_TOK)) {
dcl(OUTER_SCOPE);
}
else if (is(EOP_TOK)) {
RETURN_VOID(fn_name);
}
else if (is(COMMA_TOK)) {
error("External comma ignored");
get_token();
}
else if (is(SEMICOLON_TOK)) {
error("External semicolon ignored");
get_token();
}
else if (is(RCURLY_TOK)) {
error("External '}' ignored");
get_token();
}
else if (is(LCURLY_TOK)) {
error("Check program structure: { in outer context");
get_token();
}
else {
err3( "'",
pr_tok(),
"' ignored: outer declaration expected");
get_token();
}
}
}
/* =============== Local routines =============== */
/*
Skip over any special modifier keywords used by
Microsoft C or Turbo C.
Turboc: asm interrupt
Microsoft: fortran
Both: cdecl, far, huge, near, pascal
*/
void
allow_mkeys(void)
{
char * p;
TRACETOK("allow_mkeys");
p = &t_symbol[0];
while (is(ID_TOK)) {
if ( str_eq(p, "asm") ||
str_eq(p, "cdecl") ||
str_eq(p, "far") ||
str_eq(p, "fortran") ||
str_eq(p, "interrupt") ||
str_eq(p, "huge") ||
str_eq(p, "near") ||
str_eq(p, "pascal")
) {
get_token();
}
else {
break;
}
}
RETURN_VOID("allow_mkeys");
}
/*
Parse a formal paramenter list.
This may be an old style list (id's only) or a new style list.
The opening paren has already been read.
*/
static void
fp_list(en_scope scope)
{
bool no_tail;
en_scope this_scope;
SL_NAME(fn_name, "fp_list");
TRACETOK(fn_name);
TRACEPN(fn_name, printf("(%s)\n", pr_scope(scope)));
/* Set scope to NULL_SCOPE on recursive entry to this routines. */
if ( scope == NULL_SCOPE ||
scope == NEW_FORMAL_SCOPE ||
scope == OLD_FORMAL_SCOPE) {
this_scope = NULL_SCOPE;
}
else {
this_scope = NEW_FORMAL_SCOPE;
}
while (!is(RPAREN_TOK)) {
/* Parse the id (old style) or the dcl (new style) */
allow_mkeys();
if(is_type() || is(ID_TOK)) {
sd_dcl(this_scope);
no_tail = type_head(this_scope);
if (!no_tail) {
type_tail(this_scope);
}
sd_end(this_scope, SEMICOLON_TOK);
}
else if (is(DOTS3)) {
/* Variable number of parameters. */
get_token();
}
else {
goto bad_list;
}
if (is(COMMA_TOK)) {
get_token();
}
else if (is(RPAREN_TOK)) {
break;
}
else {
goto bad_list;
}
}
/* Eat the closing paren. */
get_token();
RETURN_VOID(fn_name);
bad_list:
err3( "Unexpected '",
pr_tok(),
"' seen in formal parameter list");
needend(RPAREN_TOK);
RETURN_VOID(fn_name);
}
/*
Parse the old style of declaration of argument types.
*/
static void
t_list(void)
{
SL_NAME(fn_name, "t_list");
TRACETOK(fn_name);
while(is_type()) {
dcl(OLD_FORMAL_SCOPE);
}
RETURN_VOID(fn_name);
}
/* Parse a list of declarations of array bounds. */
static void
array(void)
{
SL_NAME(fn_name, "array");
TRACETOK(fn_name);
while (is(LBRACK_TOK)) {
get_token();
if (is(RBRACK_TOK)) {
/* [] is valid as an array bounds (sometimes). */
get_token();
}
else {
con_expr(RBRACK_TOK);
need(RBRACK_TOK);
}
}
RETURN_VOID(fn_name);
}
/*
Parse a function declaration or definition.
The opening '(' of the formal parameter list has alread been eaten.
*/
void
function(en_scope scope)
{
SL_NAME(fn_name, "function");
TRACETOK(fn_name);
TRACEPN(fn_name, printf("(%s)\n", pr_scope(scope)));
/* Make sure a function definition is valid here. */
if (scope == STRUCT_SCOPE) {
error("Function defined in struct or union");
}
else if (scope != OUTER_SCOPE) {
error("Nested function definition");
}
else if (prev_dcl > 0) {
warning("Function not expected here");
}
/* Parse the old-style list of parameter types. */
t_list();
/*
We have a function DEFINITION.
Indicate that '}' ends dcl instead of ';'
WARNING: t_list won't work if func_def is TRUE.
*/
func_def = TRUE;
if (!is(LCURLY_TOK)) {
error("Expecting '{' following formal declarations");
RETURN_VOID(fn_name);
}
/* Set the